package com.ykt.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 集合数组工具
 *
 * @author long.hua
 * @version 1.0.0
 * @since 2016-01-21 00:24
 */
public class Colls {

    private final static Logger LOGGER = LoggerFactory.getLogger(Colls.class);


    public static <T> boolean notEmpty(Collection<T> colls) {
        return !isEmpty(colls);
    }

    public static <T> boolean isEmpty(Collection<T> colls) {
        return colls == null || colls.isEmpty();
    }

    public static <K, V> boolean notEmpty(Map<K, V> map) {
        return !isEmpty(map);
    }

    public static <K, V> boolean isEmpty(Map<K, V> map) {
        return map == null || map.isEmpty();
    }

    public static <T> boolean notEmpty(T[] array) {
        return !isEmpty(array);
    }

    /**
     * 原始类型的数组需要转换为其包装类型的数组
     */
    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length == 0;
    }

    @SafeVarargs
    public static <T> List<T> array2List(T... t) {
        if (t == null || t.length == 0) {
            return null;
        }

        List<T> list = new ArrayList<>(t.length);

        Collections.addAll(list, t);

        return list;
    }

    @SafeVarargs
    public static <T> Set<T> array2Set(T... array) {
        if (array == null || array.length == 0) {
            return null;
        }

        Set<T> set = new HashSet<>(array.length);

        Collections.addAll(set, array);

        return set;
    }

    @SafeVarargs
    public static <T> Map<T, T> array2Map(T[]... array) {
        if (isEmpty(array)) {
            return null;
        }

        Map<T, T> map = new HashMap<>(array.length);

        for (T[] ts : array) {
            if (isEmpty(ts) || ts.length < 2) {
                throw new RuntimeException("array to map error, the length little 2!");
            }
            map.put(ts[0], ts[1]);

        }

        return map;
    }

    public static <T> List<T> toList(Collection<T> set) {
        if (isEmpty(set)) {
            return null;
        }

        List<T> list = new ArrayList<>(set.size());
        list.addAll(set);
        return list;
    }

    public static <T> Set<T> toSet(Collection<T> list) {
        if (isEmpty(list)) {
            return null;
        }

        Set<T> set = new HashSet<>(list.size());
        set.addAll(list);
        return set;
    }

    @SuppressWarnings("unchecked")
    public static <K, T> Map<K, T> toMap(Collection<T> list, String fieldName4Key) {
        if (Colls.isEmpty(list) || fieldName4Key == null || fieldName4Key.isEmpty()) {
            return new HashMap<>(0);
        }

        Map<K, T> map = new HashMap<>(list.size());

        for (T t : list) {
            if (t != null) {

                K key = getKey(t, fieldName4Key);
                if (key != null) {

                    map.put(key, t);
                }
            }
        }

        return map;
    }

    @SuppressWarnings("unchecked")
    public static <K, T, V> Map<K, V> toMap(Collection<T> list, String fieldName4Key, String fieldName4Value) {
        Map<K, V> map = new HashMap<>();
        for (T t : list) {
            if (t != null) {

                K key = getKey(t, fieldName4Key);
                V value = getKey(t, fieldName4Value);
                if (key != null && value != null) {

                    map.put(key, value);
                }
            }
        }
        return map;
    }

    @SuppressWarnings("unchecked")
    public static <K, T> Map<K, List<T>> toListMap(Collection<T> list, String fieldName) {
        return toListMap(list, fieldName, false);
    }

    /**
     * 把list转换以指定属性值为key的map
     *
     * @param list
     * @param fieldName
     * @param distinct  是否要去重
     * @param <K>       以属性值为map的Key
     * @param <T>       带指定属性名的对象
     * @return
     */
    public static <K, T> Map<K, List<T>> toListMap(Collection<T> list, String fieldName, boolean distinct) {
        Map<K, List<T>> map = new HashMap<>();
        for (T t : list) {

            K key = getKey(t, fieldName);
            if (key != null) {

                if (!map.containsKey(key)) {
                    map.put(key, new ArrayList<T>());
                }

                if (!distinct) {
                    map.get(key).add(t);
                } else {
                    if (!map.get(key).contains(t)) {
                        map.get(key).add(t);
                    }
                }
            }
        }

        return map;
    }

    public static <K, T> Map<K, Set<T>> toSetMap(Collection<T> list, String fieldName) {
        Map<K, Set<T>> map = new HashMap<>();

        for (T t : list) {
            K key = getKey(t, fieldName);
            if (key != null) {

                if (!map.containsKey(key)) {
                    map.put(key, new HashSet<T>());
                }

                map.get(key).add(t);
            }

        }

        return map;
    }


    public static <K, T> List<K> toKeyList(Collection<T> list, String fieldName) {
        List<K> keys = new ArrayList<>();

        for (T t : list) {

            K key = getKey(t, fieldName);
            if (key != null) {

                keys.add(key);
            }
        }

        return keys;
    }

    public static <K, T> Set<K> toKeySet(Collection<T> list, String fieldName) {
        Set<K> keys = new HashSet<>();
        for (T t : list) {

            K key = getKey(t, fieldName);
            if (key != null) {

                keys.add(key);
            }
        }

        return keys;
    }

    @SuppressWarnings("unchecked")
    private static <K> K getKey(Object t, String fieldName) {
        for (Class<?> clazz = t.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                return (K) field.get(t);
            } catch (Exception e) {
                // 如果这里的异常打印或者往外抛，就不会执行clazz = clazz.getSuperclass()，最后就不会进入到父类中了
            }
        }

        return null;
    }

    public static <T> Collection<T> filterNull(Collection<T> coll) {
        if (notEmpty(coll)) {
            Iterator<T> iter = coll.iterator();
            while (iter.hasNext()) {
                if (iter.next() == null) {
                    iter.remove();
                }
            }
        }

        return coll;
    }

    public static <T> List<T> subList(List<T> list, int offset, int pageSize) {
        // 开始结束位置
        int begin = offset > list.size() ? list.size() : offset;
        int end = (offset + pageSize) > list.size() ? list.size() : (offset + pageSize);

        // 返回分页数据
        return new ArrayList<>(list.subList(begin, end));
    }

}
